from panda3d.core import CollisionTraverser,CollisionNode
from panda3d.core import CollisionHandlerQueue,CollisionRay
from panda3d.core import BitMask32
from direct.actor.Actor import Actor

class AbstractFamiliar:
    """ Class an abstract model of a familiar.
    """
    
    _directObjectParent = None
    _actor = None
    _name = 'Not yet implemented'
    _modelFilePath = 'Not yet implemented'
    
    def __init__(self, DirectObject, playerPos):
        """ Init. It sets directObject parent and, basing on it, creates new
            instance of Inventory class. It also calls methods to set actor
            and collisions.
            
            params:
            DirectObject - 'world' which the player interacts with 
        """
        
        self._directObjectParent = DirectObject
        
        self.setUpFamiliar(playerPos)
        self.setUpCollisions()
        
    def setUpFamiliar(self, playerPos):
        """ Method sets up model and animations for player character.
        """
        # needs to be implemented in the actual subclass
        pass
        
    def moveActor(self):
        """ Method defines what to do when the actor is supposed to move
        (animations management).
        """
        # needs to be implemented in the actual subclass
        pass
        
    def stopActor(self):
        """ Method defines what to do when the actor is supposed to stop
            (animations management)
        """
        # needs to be implemented in the actual subclass
        pass
        
    def setPos(self, playerPos):
#        code similar to the camera's placing

        if self._actor is None:
            return
            
        famVec = playerPos - self._actor.getPos()
        famVec.setZ(0)
        famDist = famVec.length()
 
        famVec.normalize()
        if (famDist > 2.0):
            self._actor.setPos(self._actor.getPos() + famVec*(famDist-2.0))
            famDist = 2.0
            
        if (famDist < 1.0):
            self._actor.setPos(self._actor.getPos() - famVec*(1.0-famDist))
            famDist = 1.0
            
        
    def setHpr(self, playerHpr):
        if self._actor is None:
            return
        
        self._actor.setHpr(playerHpr)
        
    def lookAt(self, playerActor):
        if self._actor is None:
            return
        
        self._actor.lookAt(playerActor)
        self._actor.setH(self._actor.getH() - 180)
        self._actor.setP(0)
        self._actor.setR(0)
        
    def setUpCollisions(self):
        if self._actor is None:
            return
        
        familiarGroundRay = CollisionRay()
        familiarGroundRay.setOrigin(0,0,1000)
        familiarGroundRay.setDirection(0,0,-1)
        
        familiarGroundCol = CollisionNode('familiarRay')
        familiarGroundCol.addSolid(familiarGroundRay)
        
        familiarGroundCol.setFromCollideMask(BitMask32.bit(0))
        familiarGroundCol.setIntoCollideMask(BitMask32.allOff())
        
        dirObjParent = self._directObjectParent
        
        familiarGroundColNp = dirObjParent.getPlayerFamiliarActor().attachNewNode(
            familiarGroundCol
        )
        
        dirObjParent.getColTraverser().addCollider(
              familiarGroundColNp
            , dirObjParent._familiarGroundHandler
        )
        
        